/**
 * Java lambda表达式的简单例子:
 * 1. 不需要参数,返回值为 5
 * () -> 5
 * <p>
 * 2. 接收一个参数(数字类型),返回其2倍的值
 * x -> 2 * x
 * <p>
 * 3. 接受2个参数(数字),并返回他们的差值
 * (x, y) -> x – y
 * <p>
 * 4. 接收2个int型整数,返回他们的和
 * (int x, int y) -> x + y
 * <p>
 * 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
 * (String s) -> System.out.print(s)
 */

package lambda;

import annotationtest.customannotations.Apple;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class LambdaTest {

    @FunctionalInterface
    interface Converter{
        Integer convert(String from);
    }

    @FunctionalInterface
    interface MyTest{
        String test(String from,int a,int b);
    }
    @FunctionalInterface
    interface YouTest{
        Apple makeApple();
    }
    static String[] data = {"1", "Rafael Nadal", "Novak Djokovic",
            "Stanislas Wawrinka", "David Ferrer",
            "Roger Federer", "Andy Murray",
            "Tomas Berdych", "Juan Martin Del Potro",
            "Richard Gasquet", "John Isner", "2"};

    public static void main(String[] args) {
//        printArray(null);
//        test2();
//        test3(data);
//        test4(data);
        test4(data);
        Converter converter = from -> Integer.valueOf(from);
        Converter converter1 = Integer::valueOf;  //调用类方法
        Converter converter2 = "vsdewe"::indexOf; //调用实例方法
        MyTest mt = String::substring;//调用类对象的实例方法,第一个参数作为substring方法的调用者，剩下的作为substring的调用参数
        YouTest yt = Apple::new;//引用构造器
    }

    private static void printArray(String[] array) {
        String[] defalut = {"Rafael Nadal", "Novak Djokovic",
                "Stanislas Wawrinka",
                "David Ferrer", "Roger Federer",
                "Andy Murray", "Tomas Berdych",
                "Juan Martin Del Potro"};
        if (array == null) {
            array = defalut;
        }
        List<String> players = Arrays.asList(array);
        printArray(players);
    }

    /**
     * 遍历List
     * @param players 需要打印的List
     */
    private static void printArray(List<String> players) {
        // 以前的循环方式
//        for (String player : players) {
//            System.out.print(player + ";");
//        }
//        System.out.println();
//        System.out.println("----------------使用lambda方式打印-----------------");
        // 使用 lambda 表达式以及函数操作(functional operation)
        players.forEach((item) -> System.out.print(item + ";"));
        System.out.println();
//        System.out.println("----------------使用::方式打印-----------------");
        // 在 Java 8 中使用双冒号操作符(double colon operator)
//        players.forEach(System.out::println);
    }

    /**
     * 在图形用户界面程序中,匿名类可以使用lambda表达式来代替。 同样,在实现Runnable接口时也可以这样使用
     */
    private static void test2() {
        // 使用匿名内部类
        JFrame app = new JFrame("Test2");
        app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        app.setSize(400, 300);
        app.setLocationByPlatform(true);
        Container container = app.getContentPane();
        container.setLayout(new FlowLayout(FlowLayout.LEFT));
        JButton btn = new JButton("普通方式设置点击事件");
        JButton btn2 = new JButton("Lambda方式设置点击事件");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("普通方式设置点击事件");
            }
        });

        // 或者使用 lambda expression
        btn2.addActionListener(listener -> System.out.println("Lambda方式设置点击事件"));
        container.add(btn);
        container.add(btn2);
//        app.setVisible(true); //测试时候打开

        // 1.1使用匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("1.1使用匿名内部类");
            }
        }).start();

        // 1.2使用 lambda expression
        new Thread(() -> System.out.println("1.2使用 lambda expression")).start();

        // 2.1使用匿名内部类
        Runnable race1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("2.1使用匿名内部类");
            }
        };

        // 2.2使用 lambda expression
        Runnable race2 = () -> System.out.println("2.2使用 lambda expression");

        // 直接调用 run 方法(没开新线程哦!)
        race1.run();
        race2.run();
    }

    /**
     * 使用Lambdas排序集合
     * @param players 需要排序的数组
     */
    private static void test3(String[] players) {
        // 1.1 使用匿名内部类根据 name 排序 players
        Arrays.sort(players, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return (s1.compareTo(s2));
            }
        });

        // 1.2 使用 lambda expression 排序 players
        Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
        Arrays.sort(players, sortByName);

        // 1.3 也可以采用如下形式:
        Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
        Arrays.sort(players, (String::compareTo));
        printArray(players);
    }

    private static void test4(String[] players) {
        // 1.1 使用匿名内部类根据 surname 排序 players
        Arrays.sort(players, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        });
        printArray(players);
        // 1.2 使用 lambda expression 排序,根据 surname
        Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
        printArray(players);
        // 2.1 使用匿名内部类根据 name lenght 排序 players
        Arrays.sort(players, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return (s1.length() - s2.length());
            }
        });
        printArray(players);

        // 2.2 使用 lambda expression 排序,根据 name lenght
        Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());
        Arrays.sort(players, sortByNameLenght);
        printArray(players);
        // 2.3 or this
        Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));
        printArray(players);

        // 3.1 使用匿名内部类排序 players, 根据最后一个字母
        Arrays.sort(players, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
            }
        });
        printArray(players);
        // 3.2 使用 lambda expression 排序,根据最后一个字母
        Comparator<String> sortByLastLetter = (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
        Arrays.sort(players, sortByLastLetter);
        printArray(players);
        // 3.3 or this
        Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));
        printArray(players);
    }
}

